import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output, State
import numpy as np
import plotly.graph_objects as go
from components.vectors_component import get_vectors_component, register_vectors_callbacks
from components.matrices_component import get_matrices_component, register_matrices_callbacks
from components.vector_spaces import VectorSpaces
from components.eigen_component import get_eigen_component, register_eigen_callbacks

app = dash.Dash(__name__, suppress_callback_exceptions=True, serve_locally=True, assets_folder='assets')

# 初始化所有页面组件
app.vectors_component = get_vectors_component()
app.matrices_component = get_matrices_component()
app.eigen_component = get_eigen_component()
app.vector_spaces = VectorSpaces()

app.layout = html.Div([
    html.H1('线性代数可视化演示'),
    
    dcc.Location(id='url', refresh=False),
    
    html.Div([
        html.Div([
            dcc.Link('向量运算', href='/vectors', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('矩阵运算', href='/matrices', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('矩阵向量乘法', href='/matrix-vector', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('特征值与特征向量', href='/eigen', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('向量空间', href='/vector-spaces', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('向量点积和叉积', href='/vectors-dot-cross', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('向量加法、减法和标量乘法', href='/vectors-add-sub-mul', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
            dcc.Link('矩阵高级运算', href='/matrices-advanced', style={'display': 'block', 'padding': '10px', 'margin': '5px 0', 'border': '1px solid #ddd', 'borderRadius': '5px'}),
        ], style={'width': '20%', 'float': 'left', 'padding': '20px'}),
        
        html.Div(id='page-content', style={'width': '75%', 'float': 'left', 'padding': '20px'})
    ])
])

# 页面路由回调
@app.callback(
    Output('page-content', 'children'),
    [Input('url', 'pathname')]
)
def display_page(pathname):
    if pathname == '/vectors':
        return app.vectors_component
    elif pathname == '/matrices':
        return app.matrices_component
    elif pathname == '/eigen':
        return app.eigen_component
    elif pathname == '/vector-spaces':
        return app.vector_spaces.get_component()
    elif pathname == '/matrix-vector':
        return html.Div([
            html.H1('矩阵向量乘法可视化'),
            

            
            # 矩阵元素输入
            html.Div([
                html.Label('矩阵A:'),
                html.Div([
                    dcc.Input(id='a11', type='number', value=1, style={'width': '50px'}),
                    dcc.Input(id='a12', type='number', value=0.5, style={'width': '50px'}),
                    dcc.Input(id='a13', type='number', value=0, style={'width': '50px'}),
                ], style={'margin': '10px'}),
                html.Div([
                    dcc.Input(id='a21', type='number', value=0.5, style={'width': '50px'}),
                    dcc.Input(id='a22', type='number', value=1, style={'width': '50px'}),
                    dcc.Input(id='a23', type='number', value=0, style={'width': '50px'}),
                ], style={'margin': '10px'}),
                html.Div([
                    dcc.Input(id='a31', type='number', value=0, style={'width': '50px'}),
                    dcc.Input(id='a32', type='number', value=0, style={'width': '50px'}),
                    dcc.Input(id='a33', type='number', value=1, style={'width': '50px'}),
                ], style={'margin': '10px'}),
            ]),
            
            # 向量元素输入
            html.Div([
                html.Label('向量x:'),
                html.Div([
                    dcc.Input(id='x1', type='number', value=1, style={'width': '50px'}),
                    dcc.Input(id='x2', type='number', value=1, style={'width': '50px'}),
                    dcc.Input(id='x3', type='number', value=0, style={'width': '50px'}),
                ], style={'margin': '10px'}),
            ]),
            
            # 图形展示
            dcc.Graph(id='matrix-vector-plot'),
        ])
    else:
        return html.Div([
            html.H3('请从上方导航栏选择一个演示页面')
        ])

# 注册所有回调函数
register_vectors_callbacks(app)
register_matrices_callbacks(app)
register_eigen_callbacks(app)

if not hasattr(app, 'vector_spaces'):
    app.vector_spaces = VectorSpaces()
app.vector_spaces.register_callbacks(app)

# 矩阵向量乘法回调
@app.callback(
    Output('matrix-vector-plot', 'figure'),
    [Input('a11', 'value'), Input('a12', 'value'), Input('a13', 'value'),
     Input('a21', 'value'), Input('a22', 'value'), Input('a23', 'value'),
     Input('a31', 'value'), Input('a32', 'value'), Input('a33', 'value'),
     Input('x1', 'value'), Input('x2', 'value'), Input('x3', 'value')]
)
def update_figure(a11, a12, a13, a21, a22, a23, a31, a32, a33, x1, x2, x3):
    A = np.array([[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]])
    x = np.array([x1, x2, x3])
    
    Ax = np.dot(A, x)
    
    fig = go.Figure()
    
    # 添加3D向量x
    fig.add_trace(go.Scatter3d(
        x=[0, x[0]], y=[0, x[1]], z=[0, x[2]],
        mode='lines+markers',
        name='向量x',
        line=dict(color='blue', width=3),
        marker=dict(size=5)
    ))
    
    # 添加3D结果向量Ax
    fig.add_trace(go.Scatter3d(
        x=[0, Ax[0]], y=[0, Ax[1]], z=[0, Ax[2]],
        mode='lines+markers',
        name='结果Ax',
        line=dict(color='red', width=3),
        marker=dict(size=5)
    ))
    
    # 设置3D图形布局
    fig.update_layout(
        scene=dict(
            xaxis=dict(range=[-3, 3]),
            yaxis=dict(range=[-3, 3]),
            zaxis=dict(range=[-3, 3])
        ),
        title='矩阵向量乘法 Ax',
        showlegend=True
    )
    
    return fig

if __name__ == '__main__':
    app.run(debug=True)